Кратко пробежаться по плану, акцентировать внимание на том, что сегодня переходим от теоретических основ к практическим средствам ОС. Напомнить, что тема связана с предыдущей лекцией о потоках и процессах. Данная лекция фокусируется на практическом использовании API объектов синхронизации. Теоретические основы — условия корректности, алгоритмы взаимного исключения, классические задачи — подробно рассматриваются в лекции 4.
Важно проговорить ассемблерный пример пошагово — показать, что counter++ не атомарная операция. Спросить студентов, какое максимальное значение может получиться при двух потоках, увеличивающих counter 1000 раз каждый.
Четыре условия корректности — классика (Таненбаум, Дейкстра), студенты должны знать наизусть. Обратить внимание на голодание — часто забывают. Спросить: как аппаратные средства отличаются от средств ОС по уровню абстракции?
Подчеркнуть, что test_and_set и CAS выполняются атомарно на уровне процессора благодаря блокировке шины или кэш-когерентности. Спросить: почему простое присваивание lock=1 не работает для взаимного исключения?
Показать, что спинлок годится только для очень коротких критических секций. Спросить: что будет с производительностью, если 100 потоков ждут на спинлоке? Упомянуть, что в ядре Linux часто используется адаптивный спинлок.
Важный переходный слайд — от низкоуровневых средств к высокоуровневым объектам ОС. Таблицу можно не зачитывать целиком, но подчеркнуть разницу между Signaled и Nonsignaled.
Обратить внимание на параметр bWaitAll в WaitForMultipleObjects — это частый источник ошибок. Спросить: в чём разница между INFINITE и 0? Упомянуть, что WaitForSingleObject возвращает WAIT_TIMEOUT, WAIT_FAILED и WAIT_ABANDONED.
Подчеркнуть: CreateProcess создаёт и процесс, и его первичный поток — это распространённое заблуждение. Показать, что CloseHandle для pi.hThread не завершает поток, а лишь закрывает дескриптор.
Акцентировать внимание на то, что CreateThread принимает void* — нужно приводить типы. Спросить: что произойдёт, если забыть вызвать CloseHandle? Утечка дескрипторов — частая ошибка на экзамене.
Ключевой момент — TerminateThread/Process это last resort. Спросить: какие именно ресурсы не освободятся? (куча, мьютексы, файлы). Упомянуть, что в Unix SIGKILL аналогичен TerminateProcess.
CreateFile — обобщённая функция: работает с файлами, pipe, консолью, COM-портами. Обратить внимание на параметр dwShareMode — студенты часто ставят 0 и не понимают, почему другой процесс не может открыть файл.
Подчеркнуть, что ReadFile может прочитать меньше байт, чем запрошено — всегда проверять lpNumberOfBytesRead. Упомянуть, что CloseHandle в Windows закрывает дескрипторы файлов, потоков, процессов, мьютексов — единый механизм.
Ключевое отличие мьютекса от семафора — владение. Спросить: что будет, если поток освободит мьютекс, который не захватывал? (undefined behaviour в POSIX, ошибка в Windows).
Показать типичный паттерн: WaitForSingleObject + работа + ReleaseMutex. Спросить: что будет, если забыть ReleaseMutex? Ответ: deadlock для других потоков. Упомянуть WAIT_ABANDONED — ситуация, когда владелец мьютекса завершился без освобождения.
Обратить внимание на PTHREAD_MUTEX_INITIALIZER — для статической инициализации без вызова pthread_mutex_init. Спросить: зачем нужен рекурсивный мьютекс? (рефакторинг с вложенными вызовами, рекурсивные функции).
Адаптивный мьютекс — интересная тема для углублённого обсуждения: сначала спинит, потом блокируется. На экзамене часто спрашивают разницу между NORMAL и ERRORCHECK.
Напомнить, что Дейкстра предложил семафоры в 1965 году. Спросить: при каком значении счётчика семафор превращается в мьютекс? (начальное = 1, максимальное = 1). Подчеркнуть, что семафор не имеет понятия владения.
Показать, что ReleaseSemaphore может увеличивать счётчик на любое значение (не только на 1). Частый вопрос: что произойдёт, если ReleaseSemaphore увеличит счётчик сверх максимума? (ошибка, функция вернёт FALSE).
Важно различать именованные и безымянные семафоры. Безымянные — только для потоков одного процесса через общую память. sem_unlink удаляет имя из файловой системы — без этого именованный семафор «висит» после закрытия.
Сводная таблица — хороший момент для интерактива: спросить студентов, какой примитив выбрать в конкретных ситуациях. Подчеркнуть, что Critical Section — только Windows и только внутрипроцессно.
Пробежаться по ключевым моментам, дать студентам время записать. Спросить, какой пункт вызвал больше всего вопросов — разобрать ещё раз.
Вопросы 3 и 6 — наиболее вероятные темы для экзамена. Рекомендовать студентам ответить на все вопросы вслух в парах.
Задание 3 — самое важное, обязательное для всех. Задание 4 — повышенной сложности для сильных студентов. Напомнить дедлайн и формат сдачи.
Книгу Керриска (TLPI) можно найти онлайн. man pages — лучший справочник для POSIX. MSDN — для Windows API. Напомнить, что на следующей лекции будут задачи для контрольной работы.